package com.chenyaowei.order.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.chenyaowei.cart.bo.CartItemBO;
import com.chenyaowei.cart.service.ICartService;
import com.chenyaowei.common.constant.CacheConstants;
import com.chenyaowei.common.core.domain.AjaxResult;
import com.chenyaowei.common.core.redis.RedisCache;
import com.chenyaowei.common.exception.ServiceException;
import com.chenyaowei.common.utils.SecurityUtils;
import com.chenyaowei.marketing.domain.*;
import com.chenyaowei.marketing.service.*;
import com.chenyaowei.member.domain.CywMemberReceiveAddress;
import com.chenyaowei.member.service.ICywMemberReceiveAddressService;
import com.chenyaowei.order.bo.OrderCreatBO;
import com.chenyaowei.order.domain.CywOrder;
import com.chenyaowei.order.domain.CywOrderItem;
import com.chenyaowei.order.enums.OrderStatusEnum;
import com.chenyaowei.order.request.OrderSubmitRequest;
import com.chenyaowei.order.service.ICywOrderItemService;
import com.chenyaowei.order.service.ICywOrderService;
import com.chenyaowei.order.service.ICywOrderWebService;
import com.chenyaowei.order.vo.OrderConfirmVO;
import com.chenyaowei.product.domain.CywProSkuInfo;
import com.chenyaowei.product.domain.CywProSkuSaleAttrValue;
import com.chenyaowei.product.domain.CywProSpuInfo;
import com.chenyaowei.product.domain.CywProductCategory;
import com.chenyaowei.product.service.ICywProSkuInfoService;
import com.chenyaowei.product.service.ICywProSkuSaleAttrValueService;
import com.chenyaowei.product.service.ICywProSpuInfoService;
import com.chenyaowei.product.service.ICywProductCategoryService;
import com.chenyaowei.ware.service.ICywWareSkuService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.chenyaowei.common.core.domain.AjaxResult.success;

@Service
public class ICywOrderWebServiceImpl implements ICywOrderWebService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICartService cartService;

    @Autowired
    private ICywProSkuInfoService skuInfoService;

    @Autowired
    private ICywProSkuSaleAttrValueService saleAttrValueService;

    @Autowired
    private ICywCouponHistoryService couponHistoryService;

    @Autowired
    private ICywCouponSpuRelationService spuCouponService;

    @Autowired
    private ICywCouponSpuCategoryRelationService catCouponService;

    @Autowired
    private ICywProductCategoryService categoryService;

    @Autowired
    private ICywMemberReceiveAddressService memberReceiveAddressService;

    @Autowired
    private ICywOrderService orderService;

    @Autowired
    private ICywOrderItemService orderItemService;

    @Autowired
    private ICywProSpuInfoService spuInfoService;

    @Autowired
    private ICywSkuBoundsService skuBoundsService;

    @Autowired
    private ICywSpuDiscountService spuDiscountService;

    @Autowired
    private ICywSpuFullReductionService spuFullReductionService;

    @Autowired
    private ICywWareSkuService wareSkuService;

    @Autowired
    private ICywCouponInfoService couponInfoService;


    @Autowired
    private ICywCouponSpuRelationService couponSpuRelationService;

    @Autowired
    private ICywCouponSpuCategoryRelationService cywCouponSpuCategoryRelationService;

    /**
     * 确认订单
     **/
    @Override
    public OrderConfirmVO confirmOrder(Long skuId, Integer count) {
        OrderConfirmVO confirmVO = new OrderConfirmVO();
        // 1、所有的收获地址列表
        Long userId = SecurityUtils.getUserId();
        List<CywMemberReceiveAddress> addressList = memberReceiveAddressService.selectListByUserId(userId);
        confirmVO.setAddressList(addressList);
        // 2、购物项
        List<CartItemBO> items = buildCartItem(skuId, count);
        confirmVO.setItems(items);
        Set<Long> spuIds = items.stream().map(CartItemBO::getSpuId).collect(Collectors.toSet());
        // TODO 满减、折扣 信息
        // 4、其他数据自动计算

        // 5、查询用户可以使用的优惠卷
        List<CywCouponHistory> couponList = couponHistoryService.selectUseableCouponList(userId);
        if (CollectionUtils.isNotEmpty(couponList)) {
            List<Long> couponIds = couponList.stream().map(CywCouponHistory::getCouponId).collect(Collectors.toList());
            // 找到优惠卷详情
            List<CywCouponInfo> couponInfoList = couponInfoService.selectListByIds(couponIds);
            Set<CywCouponInfo> resultCoupons = new HashSet<>();
            // 全场通用的
            List<CywCouponInfo> noLimitCoupons = couponInfoList.stream().filter(item -> item.getUseType().equals(0)).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(noLimitCoupons)) {
                // 支付总金额
                BigDecimal payPrice = confirmVO.getPayPrice();
                noLimitCoupons.forEach(item -> {
                    buildCouponStatus(item, payPrice);
                });
                resultCoupons.addAll(noLimitCoupons);
            }
            // 指定分类的
            List<CywCouponInfo> catCoupons = couponInfoList.stream().filter(item -> item.getUseType().equals(1)).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(catCoupons)) {
                CywProductCategory cateQueryWrapper = new CywProductCategory();
                cateQueryWrapper.setShowStatus(0);
                List<CywProductCategory> allCategories = categoryService.selectCywProductCategoryList(cateQueryWrapper);
                // 优惠卷所关联的分类
                List<CywCouponSpuCategoryRelation> catCouponList = catCouponService.selectListByCouponIds(couponIds);
                // 优惠卷关联的分类可能是大类，商品关联的分类是小类
                Map<Long, Long> map = catCouponList.stream().collect(Collectors.toMap(CywCouponSpuCategoryRelation::getCategoryId, CywCouponSpuCategoryRelation::getCouponId));
                List<Long> catIds = catCouponList.stream().map(CywCouponSpuCategoryRelation::getCategoryId).collect(Collectors.toList());
                catIds.forEach(catId -> {
                    List<Long> descendantIds = new ArrayList<>();
                    findDescendantCatIds(catId, allCategories, descendantIds);
                    // 该优惠卷绑定的分类的所有子分类
                    List<CartItemBO> products = items.stream().filter(item -> descendantIds.contains(item.getCatelogId())).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(products)) {
                        // 购买的同类（同祖宗）商品的总价
                        BigDecimal payPrice = products.stream().map(CartItemBO::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        CywCouponInfo cywCouponInfo = catCoupons.stream().filter(item -> item.getId().equals(map.get(catId))).findFirst().get();
                        buildCouponStatus(cywCouponInfo, payPrice);
                        resultCoupons.add(cywCouponInfo);
                    }
                });
            }
            // 指定商品的
            List<CywCouponInfo> spuCoupons = couponInfoList.stream().filter(item -> item.getUseType().equals(2)).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(spuCoupons)) {
                // 优惠卷所关联的spu
                Map<Long, Long> map = spuCouponService.selectListByCouponIds(couponIds).stream().collect(Collectors.toMap(CywCouponSpuRelation::getSpuId, CywCouponSpuRelation::getCouponId));
                spuIds.forEach(spuId -> {
                    if (map.containsKey(spuId)) {
                        List<CartItemBO> products = items.stream().filter(item -> item.getSpuId().equals(spuId)).collect(Collectors.toList());
                        BigDecimal totalPrice = products.stream().map(CartItemBO::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        CywCouponInfo cywCouponInfo = spuCoupons.stream().filter(item -> item.getId().equals(map.get(spuId))).findFirst().get();
                        buildCouponStatus(cywCouponInfo, totalPrice);
                        resultCoupons.add(cywCouponInfo);
                    }
                });
            }
            // 找到能用的价格优惠面值最大的
            resultCoupons.stream().filter(item -> Boolean.TRUE.equals(item.getEnable())).sorted(Comparator.comparing(CywCouponInfo::getAmount).reversed()).findFirst().ifPresent(maxAmountCoupon -> {
                maxAmountCoupon.setChecked(true);
                confirmVO.setCouponDiscount(maxAmountCoupon.getAmount());
            });
            confirmVO.setCouponList(resultCoupons);
        }


        // 6、防重令牌 Token 防止提交订单时重复提交
        String token = IdUtil.simpleUUID();
        redisCache.setCacheObject(CacheConstants.USER_ORDER_TOKEN_PREFIX + userId, token, 30, TimeUnit.MINUTES);
        confirmVO.setOrderToken(token);
        return confirmVO;
    }

    private void buildCouponStatus(CywCouponInfo couponInfo, BigDecimal totalPrice) {
        BigDecimal minPoint = couponInfo.getMinPoint();
        if (totalPrice.compareTo(minPoint) < 0) {
            couponInfo.setEnable(false);
            couponInfo.setMsg("距使用门槛差 " + minPoint.subtract(totalPrice).setScale(2) + " 元");
        } else {
            couponInfo.setEnable(true);
        }
    }

    /**
     * 确认提交
     **/
    @Transactional
    @Override
    public AjaxResult submitOrder(OrderSubmitRequest orderSubmitRequest) {
        // 1、验证令牌『令牌的对比和删除必须保证原子性』
        String orderToken = orderSubmitRequest.getOrderToken();
/*        if (orderToken!=null && orderToken.equals(redisToken)){
            // 令牌验证通过
            // 如果不加这个if，可能会导致订单重复提交。
            if (redisCache.deleteObject(redisToken)) {
                // 处理业务。但是也有可能存在删的时候令牌刚好过期了，没删成功，导致没处理。
            }
        }else{
            //不通过
        }*/
        //lua脚本:如果redis调用get方法来获取一个key的值，这个值等于我们传过来的值，然后就把这个令牌删除，否则返回0
        //返回的是 0 - 1（删除成功）
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Long result = (Long) redisCache.execute(new DefaultRedisScript(script, Long.class), Arrays.asList(CacheConstants.USER_ORDER_TOKEN_PREFIX + SecurityUtils.getUserId()), orderToken);
        if (result == 0L) {
            throw new ServiceException("订单信息已过期，请刷新再次提交");
        }
        //令牌验证成功
        //下单：去创建订单，验价格，锁库存
        //1、创建订单，订单项等详细信息
        OrderCreatBO orderCreatBO = creatOrder(orderSubmitRequest);

        //2、验价
        BigDecimal payAmount = orderCreatBO.getOrder().getPayAmount();
        BigDecimal payPrice = orderSubmitRequest.getPayPrice();
        if (Math.abs(payAmount.subtract(payPrice).doubleValue()) > 0.01) {
            throw new ServiceException("订单商品价格发生变化，请刷新再次提交");
        }
        // 金额对比成功
        // 3、库存锁定
        List<CywOrderItem> orderItems = orderCreatBO.getOrderItems();
        Map<Long, Integer> skuCountMap = orderItems.stream().collect(Collectors.toMap(CywOrderItem::getSkuId, CywOrderItem::getSkuQuantity));
        //key: skuId, value: wareId
        Map<Long, Long> skuWareRelation = wareSkuService.lockOrderStock(skuCountMap);
        orderItems.forEach(item -> item.setWareId(skuWareRelation.get(item.getSkuId())));
        // 4、保存订单
        saveOrder(orderCreatBO, orderSubmitRequest.getSkuId() == null);

        return success(orderCreatBO.getOrder().getOrderSn());
    }

    private void saveOrder(OrderCreatBO orderCreatBO, Boolean fromCartOrNot) {
        CywOrder order = orderCreatBO.getOrder();
        orderService.insertCywOrder(order);
        List<CywOrderItem> orderItems = orderCreatBO.getOrderItems();
        orderItems.forEach(item -> item.setOrderId(order.getId()));
        orderItemService.saveBatch(orderCreatBO.getOrderItems());
        // 清购物车
        if (fromCartOrNot) {
            orderItems.forEach(item -> cartService.deleteItem(item.getSkuId()));
        }

    }

    /**
     * creatOrder 创建订单
     * buildOrder 构建订单信息
     * buildOrderItems 构建订单项信息
     * buildCartItem 构建购物项信息
     * computePrice 计算价格、积分等相关信息
     **/
    private OrderCreatBO creatOrder(OrderSubmitRequest orderSubmitRequest) {
        //1、生成订单号
        final String orderSn = IdUtil.simpleUUID();
        CywOrder cywOrder = buildOrder(orderSubmitRequest, orderSn);
        //2、获取所有的订单项
        List<CywOrderItem> orderItems = buildOrderItems(orderSubmitRequest, orderSn);
        //3、计算价格、积分等相关信息
        computePrice(cywOrder, orderItems);
        OrderCreatBO orderCreatBO = new OrderCreatBO();
        orderCreatBO.setOrder(cywOrder);
        orderCreatBO.setOrderItems(orderItems);
        return orderCreatBO;
    }

    private void computePrice(CywOrder cywOrder, List<CywOrderItem> orderItems) {
        BigDecimal total = BigDecimal.ZERO;
        //订单的总额，叠加每一个订单项的总额信息
        BigDecimal coupon = BigDecimal.ZERO;
        BigDecimal integration = BigDecimal.ZERO;
        BigDecimal promotion = BigDecimal.ZERO;

        BigDecimal gift = BigDecimal.ZERO;
        BigDecimal growth = BigDecimal.ZERO;
        BigDecimal payAmount = BigDecimal.ZERO;
        for (CywOrderItem entity : orderItems) {
            coupon = coupon.add(entity.getCouponAmount() == null ? BigDecimal.ZERO : entity.getCouponAmount());
            integration = integration.add(entity.getIntegrationAmount() == null ? BigDecimal.ZERO : entity.getIntegrationAmount());
            promotion = promotion.add(entity.getPromotionAmount() == null ? BigDecimal.ZERO : entity.getPromotionAmount());
            total = total.add(entity.getSkuPrice().multiply(new BigDecimal(entity.getSkuQuantity())));
            gift = gift.add(new BigDecimal(entity.getGiftIntegration() == null ? 0 : entity.getGiftIntegration()));
            growth = growth.add(new BigDecimal(entity.getGiftGrowth() == null ? 0 : entity.getGiftIntegration()));
            payAmount = payAmount.add(entity.getRealAmount());
        }
        //1、订单价格相关
        cywOrder.setCouponAmount(coupon);
        cywOrder.setIntegrationAmount(integration);
        cywOrder.setPromotionAmount(promotion);
        cywOrder.setTotalAmount(total);
        //应付总额
        BigDecimal totalPreferential = coupon.add(integration).add(promotion);
        BigDecimal totalPayAmount = payAmount.add(cywOrder.getFreightAmount());
        cywOrder.setPayAmount(totalPayAmount.compareTo(totalPreferential) == -1 ? BigDecimal.ZERO : totalPayAmount);
        //设置积分等信息
        cywOrder.setIntegration(gift.intValue());
        cywOrder.setGrowth(growth.intValue());
    }

    private List<CywOrderItem> buildOrderItems(OrderSubmitRequest orderSubmitRequest, String orderSn) {
        // 最后确定每个购物项的价格
        List<CartItemBO> currentUserCartItems = buildCartItem(orderSubmitRequest.getSkuId(), orderSubmitRequest.getCount());
        if (CollectionUtils.isNotEmpty(currentUserCartItems)) {
            // 获取商品的spu信息
            List<Long> spuIds = currentUserCartItems.stream().map(CartItemBO::getSpuId).collect(Collectors.toList());
            List<CywProSpuInfo> spuInfoList = spuInfoService.selectListBySpuIds(spuIds);
            // 获取商品的sku积分信息
            List<Long> skuIds = currentUserCartItems.stream().map(CartItemBO::getSkuId).collect(Collectors.toList());
            List<CywSkuBounds> skuBoundsList = skuBoundsService.selectListBySkuIds(skuIds);
            List<CywOrderItem> orderItems = currentUserCartItems.stream().map(cartItem -> {
                CywOrderItem orderItem = new CywOrderItem();
                //1、订单信息，订单号
                //2、商品spu信息
                Long spuId = cartItem.getSpuId();
                CywProSpuInfo spuInfo = spuInfoList.stream().filter(item -> item.getSpuId().equals(spuId)).findFirst().get();
                orderItem.setSpuId(spuId);
                orderItem.setSpuPic(cartItem.getSkuPic());
                orderItem.setSpuBrand(spuInfo.getBrandName());
                orderItem.setSpuName(spuInfo.getSpuName());
                orderItem.setCategoryId(spuInfo.getCatalogId());

                //3、商品的sku信息
                Long skuId = cartItem.getSkuId();
                orderItem.setSkuId(skuId);
                orderItem.setSkuName(cartItem.getTitle());
                orderItem.setSkuPic(cartItem.getSkuPic());
                orderItem.setSkuPrice(cartItem.getPrice());
                orderItem.setSkuAttrsVals(JSON.toJSONString(cartItem.getSkuAttrsVals()));
                orderItem.setSkuQuantity(cartItem.getCount());
                //4、TODO 优惠信息
                //5、积分信息
                CywSkuBounds skuBounds = skuBoundsList.stream().filter(item -> item.getSkuId().equals(skuId)).findFirst().orElse(null);
                if (skuBounds != null) {
                    orderItem.setGiftGrowth(skuBounds.getGrowBounds().multiply(new BigDecimal(cartItem.getCount().toString())).intValue());
                    orderItem.setGiftIntegration(skuBounds.getBuyBounds().multiply(new BigDecimal(cartItem.getCount().toString())).intValue());
                }
                //6、订单项的价格信息
                // 商品促销分解金额
                orderItem.setPromotionAmount(new BigDecimal("0"));
                // 优惠券优惠分解金额
//                orderItem.setCouponAmount(new BigDecimal("0"));
                // 积分优惠分解金额
                orderItem.setIntegrationAmount(new BigDecimal("0"));
                //当前订单项的实际金额。 总额-各种优惠
                BigDecimal origin = orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuQuantity()));
                BigDecimal subtract = origin.subtract(orderItem.getPromotionAmount()).subtract(orderItem.getIntegrationAmount());
                orderItem.setRealAmount(subtract);
                orderItem.setOrderSn(orderSn);
                return orderItem;
            }).collect(Collectors.toList());

            // 优惠劵
            Long couponId = orderSubmitRequest.getCouponId();
            if (couponId != null) {
                CywCouponHistory couponHistoryQueryWrapper = new CywCouponHistory();
                couponHistoryQueryWrapper.setMemberId(SecurityUtils.getUserId());
                couponHistoryQueryWrapper.setCouponId(couponId);
                List<CywCouponHistory> couponHistories = couponHistoryService.selectCywCouponHistoryList(couponHistoryQueryWrapper);
                CywCouponHistory couponHistory = couponHistories.stream().filter(item -> item.getUseTime().before(new Date()) && item.getEndTime().after(new Date()) )
                        .sorted(Comparator.comparing(CywCouponHistory::getCreateTime).reversed()).findFirst().orElse(null);
                if (couponHistory == null) {
                    throw new ServiceException("非法操作，优惠劵不存在");
                }
                CywCouponInfo couponInfo = couponInfoService.selectCywCouponInfoById(couponId);
                List<CywOrderItem> computeCouOrderItems = null;
                // 0-全场通用；1-指定分类；2-指定商品
                Integer useType = couponInfo.getUseType();
                BigDecimal couponAmount = couponInfo.getAmount();
                BigDecimal minPoint = couponInfo.getMinPoint();
                if (useType == 0) {
                    // 0->全场通用
                    computeCouOrderItems = orderItems;
                } else if (useType == 1) {
                    // 1->指定分类
                    CywProductCategory cateQueryWrapper = new CywProductCategory();
                    cateQueryWrapper.setShowStatus(0);
                    List<CywProductCategory> allCategories = categoryService.selectCywProductCategoryList(cateQueryWrapper);
                    // 优惠卷关联的分类可能是大类，商品关联的分类是小类
                    List<Long> couCatIds = cywCouponSpuCategoryRelationService.selectListByCouponId(couponId).stream().map(CywCouponSpuCategoryRelation::getCategoryId).collect(Collectors.toList());
                    List<Long> allDescendantIds = new ArrayList<>();
                    couCatIds.forEach(couCatId -> {
                        findDescendantCatIds(couCatId, allCategories, allDescendantIds);
                    });
                    computeCouOrderItems = orderItems.stream().filter(item -> allDescendantIds.contains(item.getCategoryId())).collect(Collectors.toList());
                } else if (useType == 2) {
                    // 2->指定商品
                    List<Long> couSpuIds = couponSpuRelationService.selectListByCouponId(couponId).stream().map(CywCouponSpuRelation::getSpuId).collect(Collectors.toList());
                    computeCouOrderItems = orderItems.stream().filter(item -> couSpuIds.contains(item.getSpuId())).collect(Collectors.toList());
                }
                computeCouponResolvePrice(computeCouOrderItems, couponAmount, minPoint);
            }
            return orderItems;
        }
        throw new ServiceException("非法操作，订单购物项不能为空");
    }

    private void computeCouponResolvePrice(List<CywOrderItem> orderItems, BigDecimal couponAmount, BigDecimal minPoint) {
        BigDecimal totalOrigin = orderItems.stream().map(item -> item.getSkuPrice().multiply(new BigDecimal(item.getSkuQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (minPoint.compareTo(totalOrigin) > 0) {
            throw new ServiceException("距使用门槛差 " + minPoint.subtract(totalOrigin).setScale(2) + " 元");
        }
        // 计算优惠券剩余金额
        BigDecimal resolveCouTotal = new BigDecimal("0");
        // 优惠券优惠分解金额
        BigDecimal resolveCouAmount = new BigDecimal("0");
        for (int i = 0; i < orderItems.size(); i++) {
            CywOrderItem orderItem = orderItems.get(i);
            if (i != orderItems.size() - 1) {
                resolveCouAmount = couponAmount.multiply(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuQuantity()))).divide(totalOrigin, 2, RoundingMode.HALF_UP);
                resolveCouTotal = resolveCouTotal.add(resolveCouAmount);
            } else {
                resolveCouAmount = couponAmount.subtract(resolveCouTotal);
            }
            orderItem.setCouponAmount(resolveCouAmount);
            orderItem.setRealAmount(orderItem.getRealAmount().subtract(resolveCouAmount));
        }
    }

    private CywOrder buildOrder(OrderSubmitRequest orderSubmitRequest, String orderSn) {
        CywOrder order = new CywOrder();
        order.setOrderSn(orderSn);
        Long userId = SecurityUtils.getUserId();
        order.setMemberId(userId);
        order.setCreateTime(new Date());
        order.setMemberUsername(SecurityUtils.getUsername());
        // 优惠卷
        Long couponId = orderSubmitRequest.getCouponId();
        if (couponId != null) {
            CywCouponHistory queryWrapper = new CywCouponHistory();
            //可能存在多张一样的，用最先领取的
            queryWrapper.setMemberId(userId);
            queryWrapper.setCouponId(couponId);
            List<CywCouponHistory> couponHistories = couponHistoryService.selectCywCouponHistoryList(queryWrapper);
            CywCouponHistory couponHistory = couponHistories.stream().sorted(Comparator.comparing(CywCouponHistory::getCreateTime)).findFirst().get();
            Long couponHistoryId = couponHistory.getId();
            order.setCouponHistoryId(couponHistoryId);
            // 更新优惠卷状态
            couponHistory.setOrderId(order.getId());
            couponHistory.setOrderSn(order.getOrderSn());
            couponHistory.setUseStatus(1);
            couponHistoryService.updateCywCouponHistory(couponHistory);
            couponInfoService.updateCouponUseCount(couponHistory.getCouponId(), 1);
        }
        // TODO 设置运费信息
        order.setFreightAmount(BigDecimal.ZERO);
        //设置收货人信息
        CywMemberReceiveAddress receiveAddress = memberReceiveAddressService.selectCywMemberReceiveAddressById(orderSubmitRequest.getAddressId());
        order.setReceiverName(receiveAddress.getName());
        order.setReceiverPhone(receiveAddress.getPhone());
        order.setReceiverPostCode(receiveAddress.getPostCode());
        order.setReceiverProvince(receiveAddress.getProvince());
        order.setReceiverCity(receiveAddress.getCity());
        order.setReceiverRegion(receiveAddress.getRegion());
        order.setReceiverDetailAddress(receiveAddress.getDetailAddress());

        order.setAutoConfirmDay(7);
        order.setPayType(orderSubmitRequest.getPayType());
        // 订单来源[0->PC订单；1->app订单]
        order.setSourceType(0);
        // 订单备注
        order.setNote(orderSubmitRequest.getNote());

        // 设置订单的相关状态信息
        order.setStatus(OrderStatusEnum.CREATE_NEW.getCode());

        // 未删除
        order.setDeleteStatus(0);
        return order;
    }

    private List<CartItemBO> buildCartItem(Long skuId, Integer count) {
        List<CartItemBO> items = new ArrayList<>();
        // 2、购物项
        if (skuId != null && count != null) {
            // 商品详情页直接下单的
            CywProSkuInfo skuInfo = skuInfoService.selectCywProSkuInfoBySkuId(skuId);
            List<CywProSkuSaleAttrValue> skuSaleAttrValues = saleAttrValueService.selectListBySkuIds(Arrays.asList(skuId));
            CartItemBO cartItemBO = new CartItemBO();
            cartItemBO.setSpuId(skuInfo.getSpuId());
            cartItemBO.setCatelogId(skuInfo.getCatalogId());
            cartItemBO.setSkuId(skuId);
            cartItemBO.setCount(count);
            cartItemBO.setChecked(true);
            cartItemBO.setPrice(skuInfo.getPrice());
            List<CartItemBO.SaleAttrValue> saleAttrValues = new ArrayList<>();
            skuSaleAttrValues.forEach(item -> {
                CartItemBO.SaleAttrValue saleAttrValue = new CartItemBO.SaleAttrValue();
                BeanUtils.copyProperties(item, saleAttrValue);
                saleAttrValues.add(saleAttrValue);
            });
            cartItemBO.setSkuAttrsVals(saleAttrValues);
            cartItemBO.setSkuPic(skuInfo.getSkuDefaultImg());
            cartItemBO.setTitle(skuInfo.getSkuTitle());
            cartItemBO.setTotalPrice(skuInfo.getPrice().multiply(new BigDecimal(count)).setScale(2));
            items.add(cartItemBO);

        } else {
            // 购物车选好商品下单的
            items = cartService.getUserCartItems();
        }
        return items;
    }

    /**
     * 递归找到祖宗分类id
     **/
    private List<Long> findOriginCatIds(CywProductCategory source, List<CywProductCategory> list, List<Long> originCatIds) {
        originCatIds.add(source.getCatId());
        CywProductCategory parent = list.stream().filter(item -> item.getCatId().equals(source.getParentCid())).findFirst().get();
        if (ObjectUtil.isNotEmpty(parent)) {
            findOriginCatIds(parent, list, originCatIds);
        }
        return originCatIds;
    }

    private void findDescendantCatIds(Long catelogId, List<CywProductCategory> list, List<Long> descendantIds) {
        descendantIds.add(catelogId);
        List<CywProductCategory> children = list.stream().filter(item -> item.getParentCid().equals(catelogId)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(children)) {
            children.forEach(item -> {
                findDescendantCatIds(item.getCatId(), list, descendantIds);
            });
        }
    }
}
